package com.cbs.android.module.user.user;

import android.content.Context;
import android.graphics.Bitmap;

import com.cbs.android.component.applicationutils.Global;
import com.cbs.android.component.binaryutils.BinaryUtils;
import com.cbs.android.component.network.HttpClient;
import com.cbs.android.component.push.pushinterface.PushInterface;
import com.cbs.android.component.runtimecache.RuntimeCache;
import com.cbs.android.component.sms.smsinterface.SmsHandler;
import com.cbs.android.component.sms.smsinterface.SmsInterface;
import com.cbs.android.module.user.user.cache.PushTokenCache;
import com.cbs.android.module.user.user.cache.UserCache;
import com.cbs.android.module.user.user.entity.Setting;
import com.cbs.android.module.user.user.entity.User;
import com.cbs.android.module.user.user.handler.ModuleHandler;
import com.cbs.android.module.user.user.handler.UserChangeHandler;
import com.cbs.android.module.user.user.handler.UserPushHandler;
import com.cbs.android.module.user.user.module.LoginModule;
import com.cbs.android.module.user.user.module.LogoutModule;
import com.cbs.android.module.user.user.module.RegisterModule;
import com.cbs.android.module.user.user.module.UserModuleCheckUser;
import com.cbs.android.module.user.user.module.UserModuleForgotPassword;
import com.cbs.android.module.user.user.module.UserModuleGetInformation;
import com.cbs.android.module.user.user.module.UserModuleGetSetting;
import com.cbs.android.module.user.user.module.UserModuleGetSettings;
import com.cbs.android.module.user.user.module.UserModuleModifyPassword;
import com.cbs.android.module.user.user.module.UserModuleModifyUsername;
import com.cbs.android.module.user.user.module.UserModuleSetInformation;
import com.cbs.android.module.user.user.module.UserModuleSetPushToken;
import com.cbs.android.module.user.user.module.UserModuleSetSettings;
import com.cbs.android.module.user.user.module.UserModuleVerifyCode;
import com.cbs.android.module.user.user.module.setinformation.UserModuleSetUserAvatar;
import com.cbs.android.module.user.user.module.setinformation.UserModuleSetUserHomeImage;
import com.cbs.component.android.storage.storageinterface.StorageInterface;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by broche on 1/29/16.
 */
public class UserModule {
    public static final String RuntimeCacheName = "cbs_user";
    public static final String SALT = "cbsapp";

    private static UserChangeHandler defaultLoginUserChangeHandler = null;
    private static UserChangeHandler defaultLogoutUserChangeHandler = null;
    private static UserChangeHandler defaultRegisterUserChangeHandler = null;

    private static SmsInterface smsService = null;
    private static PushInterface pushService = null;
    private static StorageInterface storageService = null;
    private static RuntimeCache runtimeCache;
    private static HttpClient httpClient;
    private static boolean debug;

    private final static Object userLock = new Object();


    public static void init(Context context, SmsInterface smsService, PushInterface pushService, StorageInterface storageService) {
        UserModule.smsService = smsService;
        UserModule.pushService = pushService;
        UserModule.storageService = storageService;

        UserModule.pushService.addPushHandler(new UserPushHandler());

        runtimeCache = new RuntimeCache(context, RuntimeCacheName);
        httpClient = Global.getHttpClient().clone();
    }

    public static void init(Context context) {
        init(context, null, null, null);
    }

    public static void setDebug(boolean debug) {
        UserModule.debug = debug;
        httpClient.setDebug(debug);
    }

    public static boolean isDebug() {
        return debug;
    }

    public static void setUser(User user) {
        synchronized (userLock) {
            runtimeCache.setValue(UserCache.class, user);
        }
    }

    public static User getUser() {
        synchronized (userLock) {
            return (User) runtimeCache.getValue(UserCache.class);
        }
    }

    public static SmsInterface getSmsService() {
        return smsService;
    }

    public static PushInterface getPushService() {
        return pushService;
    }

    public static StorageInterface getStorageService() {
        return storageService;
    }

    public static HttpClient getHttpClient() {
        return httpClient;
    }

    public static UserChangeHandler getDefaultLoginUserChangeHandler() {
        return defaultLoginUserChangeHandler;
    }

    public static void setDefaultLoginUserChangeHandler(UserChangeHandler defaultLoginUserChangeHandler) {
        UserModule.defaultLoginUserChangeHandler = defaultLoginUserChangeHandler;
    }

    public static UserChangeHandler getDefaultLogoutUserChangeHandler() {
        return defaultLogoutUserChangeHandler;
    }

    public static void setDefaultLogoutUserChangeHandler(UserChangeHandler defaultLogoutUserChangeHandler) {
        UserModule.defaultLogoutUserChangeHandler = defaultLogoutUserChangeHandler;
    }

    public static UserChangeHandler getDefaultRegisterUserChangeHandler() {
        return defaultRegisterUserChangeHandler;
    }

    public static void setDefaultRegisterUserChangeHandler(UserChangeHandler defaultRegisterUserChangeHandler) {
        UserModule.defaultRegisterUserChangeHandler = defaultRegisterUserChangeHandler;
    }

    // login
    public static void login(String username, String password, UserChangeHandler listener, ModuleHandler<User> handler) {
        LoginModule module = new LoginModule(username, password, listener, handler);
        module.execute();
    }

    public static void login(String username, String password, UserChangeHandler listener) {
        login(username, password, listener, null);
    }

    public static void login(String username, String password, ModuleHandler<User> handler) {
        login(username, password, null, handler);
    }

    public static void login(String username, String password) {
        login(username, password, null, null);
    }

    // register
    public static void register(String username, String password, String verifyCode, UserChangeHandler listener, ModuleHandler<User> handler) {
        RegisterModule module = new RegisterModule(username, password, verifyCode, listener, handler);
        module.execute();
    }

    public static void register(String username, String password, String verifyCode, UserChangeHandler listener) {
        register(username, password, verifyCode, listener, null);
    }

    public static void register(String username, String password, String verifyCode, ModuleHandler<User> handler) {
        register(username, password, verifyCode, null, handler);
    }

    public static void register(String username, String password, String verifyCode) {
        register(username, password, verifyCode, null, null);
    }

    // logout
    public static void logout(UserChangeHandler listener, ModuleHandler handler) {
        LogoutModule module = new LogoutModule(listener, handler);
        module.execute();
    }

    public static void logout(UserChangeHandler listener) {
        logout(listener, null);
    }

    public static void logout(ModuleHandler<User> handler) {
        logout(null, handler);
    }

    public static void logout() {
        logout(null, null);
    }

    // send sms code
    public static void sendSmsCode(String phone, SmsHandler handler) {
        smsService.getVerifyCode(phone, handler);
    }

    public static void sendSmsCode(String phone) {
        sendSmsCode(phone, null);
    }

    // verify code
    public static void verifyCode(String phone, String verifyCode, boolean needCheck, ModuleHandler handler) {
        UserModuleVerifyCode module = new UserModuleVerifyCode(phone, verifyCode, needCheck, handler);
        module.start();
    }

    public static void verifyCode(String phone, String verifyCode, ModuleHandler handler) {
        verifyCode(phone, verifyCode, true, handler);
    }

    public static void verifyCodeWithOutCheck(String phone, String verifyCode, ModuleHandler handler) {
        verifyCode(phone, verifyCode, false, handler);
    }

    // check user
    public static void checkUser(String username, ModuleHandler<Boolean> handler) {
        UserModuleCheckUser module = new UserModuleCheckUser(username, handler);
        module.start();
    }

    // forgot password
    public static void forgotPassword(String username, String password, String verifyCode, ModuleHandler handler) {
        UserModuleForgotPassword module = new UserModuleForgotPassword(username, password, verifyCode, handler);
        module.start();
    }

    public static void forgotPassword(String username, String password, String verifyCode) {
        forgotPassword(username, password, verifyCode, null);
    }

    // get user information
    public static void getUserInformation(ModuleHandler<User> handler) {
        UserModuleGetInformation module = new UserModuleGetInformation(handler);
        module.start();
    }

    // get setting
    public static void getSetting(String settingName, ModuleHandler<Setting> handler) {
        UserModuleGetSetting module = new UserModuleGetSetting(settingName, handler);
        module.start();
    }

    // get settings
    public static void getSettings(ModuleHandler<List<Setting>> handler) {
        UserModuleGetSettings module = new UserModuleGetSettings(handler);
        module.start();
    }

    // modify password
    public static void modifyPassword(String oldPassword, String newPassword, ModuleHandler<User> handler) {
        UserModuleModifyPassword module = new UserModuleModifyPassword(oldPassword, newPassword, handler);
        module.start();
    }

    public static void modifyPassword(String oldPassword, String newPassword) {
        modifyPassword(oldPassword, newPassword, null);
    }

    // modify username
    public static void modifyUsername(String password, String username, String verifyCode, ModuleHandler<User> handler) {
        UserModuleModifyUsername module = new UserModuleModifyUsername(password, username, verifyCode, handler);
        module.start();
    }

    public static void modifyUsername(String password, String username, String verifyCode) {
        modifyUsername(password, username, verifyCode, null);
    }

    // set user information
    public static void setUserInformation(User user, ModuleHandler<User> handler) {
        UserModuleSetInformation module = new UserModuleSetInformation(user, handler);
        module.start();
    }

    public static void setUserInformation(User user) {
        setUserInformation(user, null);
    }

    // set user avatar
    public static void setUserAvatar(Bitmap bitmap, ModuleHandler<User> handler) {
        UserModuleSetUserAvatar module = new UserModuleSetUserAvatar(bitmap, handler);
        module.start();
    }

    public static void setUserAvatar(Bitmap bitmap) {
        setUserAvatar(bitmap, null);
    }

    // set home image
    public static void setUserHomeImage(Bitmap bitmap, ModuleHandler<User> handler) {
        UserModuleSetUserHomeImage module = new UserModuleSetUserHomeImage(bitmap, handler);
        module.start();
    }

    public static void setUserHomeImage(Bitmap bitmap) {
        setUserHomeImage(bitmap, null);
    }

    // set push token
    public static void setPushToken(String pushToken, ModuleHandler handler) {
        synchronized (userLock) {
            runtimeCache.setValue(PushTokenCache.class, pushToken);
        }
        UserModuleSetPushToken module = new UserModuleSetPushToken(pushToken, handler);
        module.start();
    }

    public static void setPushToken(String pushToken) {
        setPushToken(pushToken, null);
    }

    public static void refreshPushToken(ModuleHandler handler) {
        String token = (String) runtimeCache.getValue(PushTokenCache.class);
        if (token != null && !token.equals("")) {
            setPushToken(token, handler);
        }
    }

    public static void refreshPushToken() {
        refreshPushToken(null);
    }

    // set settings
    public static void setSettings(List<Setting> settings, ModuleHandler handler) {
        UserModuleSetSettings module = new UserModuleSetSettings(settings, handler);
        module.start();
    }

    public static void setSettings(List<Setting> settings) {
        setSettings(settings, null);
    }

    public static void setSetting(String attr, String value, ModuleHandler handler) {
        List<Setting> list = new ArrayList<>();
        Setting setting = new Setting().setAttr(attr).setValue(value);
        list.add(setting);
        setSettings(list, handler);
    }

    public static void setSetting(String attr, String value) {
        setSetting(attr, value, null);
    }

    public static String getPassword(String pwd) {
        return BinaryUtils.md5((BinaryUtils.md5(pwd.getBytes()).toLowerCase() + SALT).getBytes()).toLowerCase();
    }
}
